import { arrayMethod } from './array.js'
import Dep from './dep.js'
class Observer {
  constructor(data) {
    this.dep = new Dep()
    Object.defineProperty(data, '__ob__', {
      value: this,
      enumerable: false,
      writable: true,
      configurable: true,
    })
    if(Array.isArray(data)) {
      // 对数组方法重写
      data.__proto__ = arrayMethod
      this.observeArray(data)
    }else {
      this.walk(data)
    }
  }
  walk(data) {
    const keys = Object.keys(data)
    for(let i = 0; i < keys.length; i++) {
      let key = keys[i]
      let value = data[key] 
      defineReactive(data, key, value)
    }
  }

  observeArray(data) {
    for(let i of data) {
      observe(i)
    }
  }
}

function defineReactive(data, key, value) {
  const dep = new Dep()
  const childObj = observe(value)
  Object.defineProperty(data, key, {
    get: function() {
      if(Dep.target) {
        // 如果有watcher dep就会保存watcher 同时watcher也会保存dep
        dep.depend()
      }
      if(childObj) {
        // 对整个对象或者数组添加依赖
        childObj.dep.depend()
        // 对数组进行递归收集依赖, { a: [1,2,[3,4, [5,6]]] }
        if(Array.isArray(value)) {
          console.log(value, value.__ob__);
          dependArray(value) //数组深度收集依赖
        }
      }
      return value
    },
    set: function(newVal) {
      console.log('检测到数据变化', key, value);
      value = newVal
      dep.notify();
    }
  })
}

export function observe(value) {
  if(
    Object.prototype.toString.call(value) === '[object Object]' ||
    Array.isArray(value)
  ) {
    return new Observer(value)
  }
}
function dependArray(data) {
  for(let value of data) {
    // 有__ob__属性说明已经数据观测了
    value && value.__ob__ && value.__ob__.dep.depend()
    if(Array.isArray(value)) {
      dependArray(value)
    }
  }
}